Element.prototype.getObject = function () {
  let data = {};

  let attributes = this.attributes;
  for (let i = 0; i < attributes.length; i++) {
    let attribute = attributes[i];
    if (attribute.name.length > 9 && attribute.name.substring(0, 9) == "data-obj-") {
      let oname = attribute.name.substring(9);
      let ovalue = attribute.value;
      data[toHump(oname)] = ovalue;
    } else if (attribute.name.length > 11 && attribute.name.substring(0, 11) == "data-check-") {
      let oname = attribute.name.substring(11);
      let ovalue = attribute.value;
      let $table = $(ovalue);
      let items = new Array();
      for (let j = 0; j < $table.length; j++) {
        let item = $table[j];
        if (item.getAttribute("name") == oname && item.checked) {
          let obj = item.getObject();
          let l = Object.keys(obj).length;
          if (l == 0) {
            items[items.length] = item.value;
          } else {
            items[items.length] = obj;
          }
        }
      }
      if (items.length == 0) {
        let errorMsg = this.getAttribute("data-toast-error");
        if (errorMsg == undefined) {
          errorMsg = oname + "不能为空";
        }
        //toast.failure(errorMsg);
        throw errorMsg;
      } else {
        data[toHump(oname)] = items;
      }
    } else if (attribute.name.length > 9 && attribute.name.substring(0, 9) == "data-arr-") {
      let ovalue = attribute.value;
      let oname = attribute.name.substring(9);
      ovalue = ovalue.split(',');
      if (ovalue.length > 0) {
        let temp = ovalue[0];
        if (isRealNum(temp)) {
          for (let j = 0; j < ovalue.length; j++) {
            ovalue[j] = parseInt(ovalue[j]);
          }
        }
      }
      data[toHump(oname)] = ovalue;
    }
  }

  let handle = this.getAttribute("data-handle");
  if (handle != undefined) {
    data = eval(handle);
  }

  return data;
};

Element.prototype.getForm = function () {
  let data = {};

  let inputs = this.getElementsByTagName("input");
  for (let i = 0; i < inputs.length; i++) {
    let input = inputs[i];
    let name = input.getAttribute("name");
    if (name != null) {
      let type = input.getAttribute("type");
      if (type == "radio") {
        if (input.checked == true) {
          data[toHump(name)] = input.value;
        }
      } else {
        data[toHump(name)] = input.value;
      }
    }
  }

  let selects = this.getElementsByTagName("select");
  for (let i = 0; i < selects.length; i++) {
    let select = selects[i];
    let index = select.selectedIndex;
    let value = select.options[index].value;
    let name = select.getAttribute("name");
    if (name != null) {
      data[toHump(name)] = value;
    }
  }
  
  let textareas = this.getElementsByTagName("textarea");
  for (let i = 0; i < textareas.length; i++) {
    let textarea = textareas[i];
    let name = textarea.getAttribute("name");
    if (name != null) {
      data[toHump(name)] = textarea.value;
    }
  }
  
  let images = this.getElementsByTagName("img");
  for (let i = 0; i < images.length; i++) {
    let image = images[i];
    let name = image.getAttribute("name");
    if (name != null) {
      data[toHump(name)] = image.src;
    }
  }

  let attributes = this.attributes;
  for (let i = 0; i < attributes.length; i++) {
    let attribute = attributes[i];
    if (attribute.name.length > 10 && attribute.name.substring(0, 10) == "data-form-") {
      let oname = attribute.name.substring(10);
      let ovalue = attribute.value;
      data[toHump(oname)] = ovalue;
    }
  }

  return data;
};

//================
function getMessage(headers) {
  return decodeURIComponent(headers.get("x-api-message"));
}
function getRedirect(headers) {
  return headers.get("x-api-redirect");
}

function defaultSuccessFunc(status, data, headers) {
  let message = getMessage(headers);
  let redirect = getRedirect(headers);
  if (message == null || message == "null") {
    message = data;
  }

  if (redirect == null) {
    toast.success(message, reload);
  } else {
    if (redirect.substring(0, 1) == '/') {
      redirect = location.protocol + '//' + location.host + redirect;
    }
    if (message !== "") {
      toast.success(message, () => skip(redirect, "_SELF"));
    } else {
      skip(redirect, "_SELF");
    }
  }
}
function defaultFailureFunc(status, data, headers) {
  let message = getMessage(headers);
  let redirect = getRedirect(headers);
  
  if (message == null || message == "null") {
    //message = data;
    message = JSON.stringify(data);
  }
  
  if (redirect == null) {
    toast.failure(message);
  } else {
    if (redirect.substring(0, 1) == '/') {
      redirect = location.protocol + '//' + location.host + redirect;
    }
    if (message !== "") {
      toast.warning(message, () => skip(redirect));
    } else {
      skip(redirect);
    }
  }
}

function defaultExceptionFunc(response) {
  toast.error("请求异常，详细信息可查看控制台");
  console.info(response);
}

//================
function doFetch(url, method, headers, data, successFunc, failureFunc, exceptionFunc) {
  let options = {
    credentials: "same-origin"
  };

  if (headers == undefined) {
    options.headers = {
      "Accept": "application/json,text/plain,*/*",
      "Content-Type": "application/json"
    };
  } else {
    options.headers = headers;
    if (options.headers["Accept"] == undefined) {
      options.headers["Accept"] = "application/json,text/plain,*/*";
    }
    if (options.headers["Content-Type"] == undefined) {
      options.headers["Content-Type"] = "application/json";
    }
  }
  method = method.toUpperCase();

  if (data != undefined) {
    if (method == "GET") {
      method = "POST";
      options.headers["x-method-override"] = "GET";
    }
    if (typeof (data) == "string") {
      options.body = data;
    } else {
      options.body = JSON.stringify(data);
    }
  }
  options.method = method;

  fetch(url, options).then(response => {
      response.text().then(data => {
        if (data != undefined && data != "" && (data.substring(0, 1) == "{" || data.substring(0, 1) == "[")) {
          data = JSON.parse(data);
        }
        if (response.status >= 200 && response.status < 300) {
          successFunc(response.status, data, response.headers);
        } else {
          failureFunc(response.status, data, response.headers);
        }
      });
    })
    .catch(response => {
	  console.info(response);
      if (exceptionFunc != undefined) {
        exceptionFunc(response);
      } else {
        console.info(response);
      }
    });

  return false;
}

function doMethod(url, method, data, encry, successFunc, failureFunc, exceptionFunc) {
  let headers = undefined;
  if (encry == "AES") {
  } else if (encry != undefined) {
    try {
      let encrypt = new JSEncrypt();
      encrypt.setPrivateKey('-----BEGIN RSA PRIVATE KEY-----' + encry + '-----END RSA PRIVATE KEY-----');
      data = encrypt.encrypt(JSON.stringify(data));
      headers = {
        "Content-Type": "application/json",
        "data-encry-type": "RSA-SELF"
      };
    } catch (e) {
      console.info(e);
    }
  }

  createSecretToken(url, method);

  if (successFunc == undefined) {
    successFunc = function (status, data, headers) {
      //toast.success(getMessage(headers), reload);
    };
  }
  if (failureFunc == undefined) {
    failureFunc = defaultFailureFunc;
  }
  return doFetch(url, method, headers, data, successFunc, failureFunc, exceptionFunc);
}

function get(url, successFunc, failureFunc, exceptionFunc) {
  return doMethod(url, "GET", undefined, undefined, successFunc, failureFunc, exceptionFunc)
}

function post(url, data, successFunc, failureFunc, exceptionFunc) {
  return doMethod(url, "POST", data, undefined, successFunc, failureFunc, exceptionFunc)
}

function put(url, data, successFunc, failureFunc, exceptionFunc) {
  return doMethod(url, "PUT", data, undefined, successFunc, failureFunc, exceptionFunc)
}

function del(url, data, successFunc, failureFunc, exceptionFunc) {
  return doMethod(url, "DELETE", data, undefined, successFunc, failureFunc, exceptionFunc)
}

//=============
function createSecretToken(uri, method) {
  let aesKey = localStorage["aesKey"];
  let aesIv = localStorage["aesIv"];
  if (aesKey) {
    aesKey = CryptoJS.enc.Hex.parse(aesKey.toHex());
  } else {
    return;
  }
  if (aesIv) {
    aesIv = CryptoJS.enc.Hex.parse(aesIv.toHex());
  }

  if (aesKey) {
    let secretToken = new Object();
    secretToken.createTime = new Date();
    secretToken.uuid = uuid();
    if (uri.indexOf("%") == -1) {
      secretToken.uri = encodeURI(uri);
    } else {
      secretToken.uri = uri;
    }
    secretToken.method = method;
    let src = JSON.stringify(secretToken);
    let config = {
      padding: CryptoJS.pad.Pkcs7
    };
    if (aesIv) {
      config.mode = CryptoJS.mode.CBC;
      config.iv = aesIv;
    } else {
      config.mode = CryptoJS.mode.ECB;
    }
    let enc = CryptoJS.AES.encrypt(src, aesKey, config);
    let enced = CryptoJS.enc.Base64.stringify(enc.ciphertext);
    document.cookie = "secretToken=" + enced + "; Max-Age=60; path=/";
  };
}

function skip(url, target) {
  if (!url) {
    return false;
  }

  if (url == "about:blank" || (url.length > 4 && url.substring(0, 4) == "http")) {
    if (target) {
      location.href = url;
    } else {
      window.open(url, target);
    }
    return false;
  }

  createSecretToken(url, "GET");
  if (target === undefined || target === null) {
    location.href = location.protocol + '//' + location.host + url;
  } else {
    window.open(location.protocol + '//' + location.host + url, target);
  }

  return false;
}

function reload() {
  createSecretToken(location.pathname + location.search, "GET");
  location.reload();
}

//======================
function hideModal(obj) {
}

function doThis(obj, url, method, data, successFunc, failureFunc, exceptionFunc) {
  let encry = obj.getAttribute("data-encry-type");
  if (encry == "RSA") {
    encry = document.getElementsByName("RSA");
    if (encry.length > 0) {
      encry = encry[0].getAttribute("content");
    }
  }

  let success = obj.getAttribute("data-success");
  if (success != undefined) {
    successFunc = eval(success);
  }
  let failure = obj.getAttribute("data-failure");
  if (failure != undefined) {
    failureFunc = eval(failure);
  }
  let exception = obj.getAttribute("data-exception");
  if (exception != undefined) {
    exceptionFunc = eval(exception);
  }

  hideModal(obj);

  let path = obj.getAttribute("data-path");
  if (path !== undefined && path != "" && path != null) {
    url = url + path;
  }
  //console.info(url+" "+method+" "+data+" "+encry+" "+successFunc+" "+failureFunc+" "+exceptionFunc)
  return doMethod(url, method, data, encry, successFunc, failureFunc, exceptionFunc);
}

function doMethodThis(obj, successFunc, failureFunc, exceptionFunc) {
  let url = obj.getAttribute("data-url");
  if (!url) {
    url = obj.getAttribute("href");
    if (!url) {
      url = window.location.pathname;
    }
  }
  let method = obj.getAttribute("data-method");
  if (!method) {
    method = "GET";
  }
  return doThis(obj, url, method, obj.getObject(), successFunc, failureFunc, exceptionFunc);
}

function formThis(obj, successFunc, failureFunc, exceptionFunc) {
  let url = obj.getAttribute("action");
  if (url === undefined || url === "") {
    url = window.location.pathname;
  }
  let method = obj.getAttribute("method");
  if (method === undefined || method === "") {
    method = "GET";
  }
  try {
    doThis(obj, url, method, obj.getForm(), successFunc, failureFunc, exceptionFunc);
  } catch (error) {
    console.info(error);
  }
  return false;
}

function postThis(obj, successFunc, failureFunc, exceptionFunc) {
  let url = obj.getAttribute("data-url");
  if (url === undefined || url === "") {
    url = window.location.pathname;
  }
  return doThis(obj, url, "POST", obj.getObject(), successFunc, failureFunc, exceptionFunc);
}

//==========================================
$(function () {
  let forms = document.getElementsByTagName("form");
  for (let i = 0; i < forms.length; i++) {
    let form = forms[i];
    if (form.getAttribute("onsubmit") !== null) {
      continue;
    };

    form.onsubmit = function () {
      let dialogId = form.getAttribute("data-dialog-close");
      if (dialogId) {
        dialog.close(dialogId);
      }
      return formThis(this, defaultSuccessFunc, defaultFailureFunc, defaultExceptionFunc);
    }
  }

  $('body').on('click', 'a', function () {
    let a = this;
    let method = a.getAttribute("data-method");
    if (method) {
      let msg = a.getAttribute("data-dialog-t-msg");
      if (!msg) {
        return doMethodThis(a,
          (status, data, headers) => toast.success(getMessage(headers), reload),
          (status, data, headers) => toast.failure(getMessage(headers))
        );
      }
      return true;
    } else {
      let url = a.getAttribute("href");
      if (url && !url.startWith("#") && !url.startWith("javascript") && !a.getAttribute("onclick")) {
	    let target = a.getAttribute("target");
		if (a.getAttribute("download")) {
			//window.open(url, target);
			return true;
		} else {
	        return skip(url, target);
		}
      }
      return true;
    }
  });

  let hrefs = document.querySelectorAll("*[data-href]")
  for (let i = 0; i < hrefs.length; i++) {
    let href = hrefs[i];
    href.style.cssText = href.style.cssText + "cursor:pointer;";
    let url = href.getAttribute("data-href");
    href.onclick = function () {
      return skip(url);
    };
  }
});